<template>
  <div class="actual-api-test" v-loading="loading">
    <el-form :model="editForm" :rules="editFormRules" ref="editForm" label-width="0">
      <el-row>
        <el-col :span="24">
          <div class="source-item">
            <div class="source-title linear-green">{{ $dict('$api_request_type')[editForm.apiReqType] }}</div>
            <div class="source-content">
              {{ editForm.apiUrl }}
            </div>
          </div>
        </el-col>
      </el-row>
      <div class="context-wrap" v-if="editForm.params.length">
        <div class="context-item context-title">
          <el-row>
            <el-col :span="8" align="center">参数名称</el-col>
            <el-col :span="16" align="center">绑定参数</el-col>
          </el-row>
        </div>
        <template>
          <div class="context-item" v-for="(item, index) in editForm.params" :key="index">
            <el-row>
              <el-col :span="8" align="center">{{ item.label }}</el-col>
              <el-col :span="16">
                <el-form-item
                  :prop="'params.' + index + '.value'"
                  :rules="[
                    { required: true, message: '参数信息不能为空', trigger: 'blur' },
                    { validator: checkPercent, trigger: 'blur' }
                  ]"
                >
                  <el-input placeholder="请输入参数信息" v-model="item.value"></el-input>
                </el-form-item>
              </el-col>
            </el-row>
          </div>
        </template>
      </div>
      <el-row>
        <el-col :span="24" v-if="showEditor">
          <div class="source-item params-item test-params">
            <div class="source-title">
              <span><icon-svg name="iconArts"></icon-svg></span><br />
              参数信息
            </div>
            <div class="source-content">
              <el-form-item prop="apiReqContext" class="code-input">
                <textarea id="test-req-box"></textarea>
                <el-input v-model="editForm.apiReqContext" type="textarea" :style="codeStyle"></el-input>
              </el-form-item>
            </div>
          </div>
        </el-col>
        <el-col :span="24" align="center">
          <el-button type="primary" class="test-btn" @click="goTest">开始测试</el-button>
        </el-col>
        <template v-if="showResult">
          <el-col :span="24">
            <div class="source-item params-item">
              <div class="source-title">
                <span><icon-svg name="iconLog"></icon-svg></span><br />
                测试结果
              </div>
              <div class="source-content">
                <el-form-item prop="result" class="code-input">
                  <textarea id="test-resp-box" disabled></textarea>
                </el-form-item>
              </div>
            </div>
          </el-col>
          <el-col :span="24" align="right">响应时间：{{ reqTime }} ms</el-col>
        </template>
      </el-row>
    </el-form>
  </div>
</template>

<script>
import CodeMirror from 'codemirror'
import axios from 'axios'
import qs from 'qs'
import { Loading } from 'element-ui'
export default {
  data() {
    const isJSON = (rule, value, callback) => {
      if (!value) return callback()
      try {
        var obj = JSON.parse(value)
        if (obj && typeof obj === 'object') {
          return callback()
        } else {
          return callback(new Error('请输入正确的JSON格式数据'))
        }
      } catch (e) {
        return callback(new Error('请输入正确的JSON格式数据'))
      }
    }
    return {
      loading: false,
      pacLoading: null,
      editForm: {
        apiReqType: '',
        apiUrl: '',
        apiPath: '',
        apiReqContext: '',
        token: '',
        params: []
      },
      editFormRules: {
        apiReqContext: [
          { validator: isJSON, trigger: 'blur' }
          // { max: 1000, message: '参数信息不能超过1000个字符', trigger: 'blur' }
        ]
      },
      showEditor: false,
      apiReqEditor: null,
      apiRespEditor: null,
      showResult: false,
      reqTime: 0,
      codeStyle: {
        height: 0,
        overflow: 'hidden'
      }
    }
  },
  watch: {
    loading(val) {
      if (val) {
        this.pacLoading = Loading.service({
          target: '.pac-personal-drawer .el-drawer__body',
          spinner: 'el-icon-loading',
          customClass: 'tag-import-loading'
        })
      } else {
        this.pacLoading.close()
        this.pacLoading = null
      }
    }
  },
  methods: {
    checkPercent(rule, value, callback) {
      if (value.indexOf('%') >= 0) return callback(new Error('参数不能包含%符号'))
      else return callback()
    },
    getDetail(apiId) {
      this.$ajax({
        url: this.$ajax.setUrl(`index/indexApi/${apiId}`),
        method: 'get',
        params: this.$ajax.setParams()
      }).then(({ data }) => {
        if (data && data.code === '0') {
          this.editForm.apiReqType = data.data.apiReqType
          this.editForm.apiUrl = data.data.apiUrl
          this.editForm.apiPath = data.data.apiPath
          this.editForm.apiReqContext = data.data.apiReqContext
          if (data.data.apiReqContext.length) {
            this.showEditor = true
            this.$nextTick(() => this.initText())
          } else {
            this.showEditor = false
          }
          this.initParams()
        } else {
          this.$message.error(data.data || data.msg)
        }
      })
    },
    initText() {
      if (!this.apiReqEditor) {
        this.apiReqEditor = CodeMirror.fromTextArea(document.getElementById('test-req-box'), {
          mode: 'application/json',
          lineWrapping: true,
          foldGutter: true,
          gutters: ['CodeMirror-foldgutter']
        })
      }
      this.apiReqEditor.setValue(this.editForm.apiReqContext)
      this.apiReqEditor.refresh()
      this.apiReqEditor.on('blur', this.resreshReq)
    },
    resreshReq() {
      let content = this.apiReqEditor.getValue()
      this.editForm.apiReqContext = content
      this.$refs.editForm.validateField('apiReqContext')
    },
    initParams() {
      this.editForm.params = []
      let urls = this.editForm.apiUrl.split('/')
      for (let i = 0; i < urls.length; i++) {
        if (urls[i] && urls[i].indexOf('{') >= 0 && urls[i].indexOf('}') >= 0) {
          let label = urls[i].split('{')[1].split('}')[0]
          this.editForm.params.push({
            label: label,
            value: ''
          })
        }
      }
    },
    goTest() {
      this.$refs.editForm.validate(valid => {
        if (valid) {
          let url = this.editForm.apiUrl
          this.editForm.params.forEach(item => {
            url = url.replace('{' + item.label + '}', item.value)
          })
          let config = {
            method: this.editForm.apiReqType === 1 ? 'GEt' : 'POST',
            url: url,
            headers: {
              'Content-Type': 'application/json; charset=utf-8'
            },
            timeout: 1000 * 30,
            withCredentials: false,
            paramsSerializer: function(params) {
              return qs.stringify(params, { allowDots: true, indices: !!params.d })
            }
          }
          if (this.editForm.apiReqContext) {
            if (this.editForm.apiReqType === 1)
              config.params = this.$ajax.setParams(JSON.parse(this.editForm.apiReqContext))
            else config.data = this.$ajax.setData(JSON.parse(this.editForm.apiReqContext))
          }
          this.loading = true
          this.showResult = true
          this.$nextTick(() => {
            if (!this.apiRespEditor) {
              this.apiRespEditor = CodeMirror.fromTextArea(document.getElementById('test-resp-box'), {
                mode: 'application/json',
                lineWrapping: true,
                foldGutter: true,
                readOnly: true,
                gutters: ['CodeMirror-foldgutter']
              })
            }
            this.apiRespEditor.setValue('')
            this.apiRespEditor.refresh()
            this.reqTime = 0
            let time = new Date().getTime()
            axios(config)
              .then(data => {
                let receiveTime = new Date().getTime()
                this.reqTime = receiveTime - time
                let result = JSON.stringify(data.data)
                this.apiRespEditor.setValue(JSON.stringify(JSON.parse(result), null, 4))
                this.apiRespEditor.refresh()
                this.loading = false
              })
              .catch(() => {
                this.$message.error('网络连接错误')
                this.loading = false
              })
          })
        }
      })
    },
    clearForm() {
      this.editForm.apiReqType = ''
      this.editForm.apiUrl = ''
      this.editForm.apiReqContext = ''
      this.editForm.token = ''
      this.editForm.params = []
      this.showEditor = false
      this.apiReqEditor = null
      this.apiRespEditor = null
      this.showResult = false
    }
  }
}
</script>

<style lang="scss">
.actual-api-test {
  .source-item {
    width: 100%;
    height: 45px;
    margin-bottom: 20px;
    box-shadow: #eee 0 0 10px;
    position: relative;
    .source-title {
      font-weight: bold;
      width: 150px;
      height: 100%;
      padding-left: 50px;
      line-height: 45px;
      color: #fff;
      position: absolute;
      z-index: 2;
      &:before {
        width: 10px;
        height: 10px;
        content: '';
        background-color: #eee9ff;
        border: 2px solid #cfc7ee;
        margin-top: -5px;
        position: absolute;
        top: 50%;
        left: 20px;
        border-radius: 50%;
      }
      &:after {
        width: 0;
        height: 0;
        content: '';
        margin-top: -10px;
        border-top: 10px solid transparent;
        border-bottom: 10px solid transparent;
        position: absolute;
        top: 50%;
        right: -10px;
      }
      &.linear-green:after {
        border-left: 10px solid #36b999;
      }
    }
    .source-content {
      line-height: 45px;
      padding-left: 170px;
    }
    .el-select .el-input__inner,
    .el-input .el-input__inner {
      height: 45px;
      line-height: 45px;
      border-color: #fff;
    }
    &.test-params {
      .source-title {
        &:before,
        span {
          background-color: #3992fc;
        }
      }
    }
  }
  .context-wrap {
    box-shadow: 1px 2px 5px 5px #eee;
    border-radius: 5px;
    overflow: hidden;
  }
  .context-item {
    line-height: 40px;
    &.context-title {
      height: 40px;
      line-height: 40px;
      font-weight: bold;
      color: #fff;
      background-color: #3992fc;
    }
    &:nth-of-type(2) {
      margin-top: 22px;
    }
    & + .context-item {
      .el-col-8 {
        border-right: 1px solid #3992fc;
      }
      .el-col-16 {
        padding: 0 20px;
      }
    }
  }
  .params-item {
    height: 340px;
    border-top-left-radius: 5px;
    border-bottom-left-radius: 5px;
    overflow: hidden;
    .source-title {
      width: 200px;
      padding-left: 0;
      color: #666;
      text-align: center;
      &:before {
        width: 5px;
        height: 100%;
        content: '';
        border: 0;
        margin-top: 0;
        background-color: #f2a85d;
        position: absolute;
        top: 0;
        left: 0;
        border-radius: 0;
      }
      &:after {
        width: 1px;
        height: auto;
        margin-top: 0;
        content: '';
        background-color: #eee;
        position: absolute;
        top: 10px;
        right: 10px;
        bottom: 10px;
      }
      span {
        display: inline-block;
        width: 50px;
        height: 50px;
        margin-top: 125px;
        color: #fff;
        background-color: #f2a85d;
        text-align: center;
        border-radius: 50%;
        svg {
          width: 30px;
          height: 30px;
          margin-top: 10px;
        }
      }
    }
    .source-content {
      padding: 20px 20px 20px 200px;
      line-height: normal;
      .el-form-item__content {
        line-height: normal;
      }
      .CodeMirror {
        height: 300px;
        border: 1px solid #eee;
      }
    }
  }
  .test-btn {
    margin: 20px 0;
    padding-left: 50px;
    padding-right: 50px;
  }
  .code-input .el-form-item__error {
    margin-top: -15px;
  }
}
</style>
